package com.zzedu.manager.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.zzedu.common.enums.CommonEnums;
import com.zzedu.common.enums.DeletedEnums;
import com.zzedu.common.utils.SecurityUtils;
import com.zzedu.common.utils.StringUtils;
import com.zzedu.common.utils.security.LoginUser;
import com.zzedu.domain.*;
import com.zzedu.enmuns.ConfigEnums;
import com.zzedu.manager.IZzExerciseBookManager;
import com.zzedu.manager.IZzPictureBookManager;
import com.zzedu.manager.IZzUploadFileManager;
import com.zzedu.result.Result;
import com.zzedu.result.ResultEnum;
import com.zzedu.service.*;
import com.zzedu.stu.req.QueryAllZzPictureNode;
import com.zzedu.stu.req.QueryPageZzPictureBook;
import com.zzedu.stu.req.QueryPictureByNodeContent;
import com.zzedu.stu.req.QueryUnitList;
import com.zzedu.stu.rsp.ApiZzPictureBookNodeVO;
import com.zzedu.stu.rsp.ApiZzPictureBookVO;
import com.zzedu.stu.rsp.ApiZzPictureContentVO;
import com.zzedu.system.service.ISysConfigService;
import com.zzedu.utils.PageData;
import com.zzedu.vo.ZzUploadFileVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.time.ZoneOffset;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class ZzZzPictureBookManagerImpl implements IZzPictureBookManager {

    @Autowired
    IZzPictureBookService zzPictureBookService;

    @Autowired
    IZzUploadFileManager zzUploadFileManager;

    @Autowired
    IZzPictureNodeService zzPictureNodeService;
    @Autowired
    IZzSubjectContentService zzSubjectContentService;

    @Autowired
    ISysConfigService sysConfigService;

    @Autowired
    IZzTimetableService zzTimetableService;

    @Autowired
    IZzStudentService zzStudentService;

    @Autowired
    IZzCourseService zzCourseService;
    @Autowired
    IZzExerciseBookService zzExerciseBookService;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    IZzExerciseBookManager zzExerciseBookManager;

    @Autowired
    IZzClassesSendStudentService zzClassesSendStudentService;

    @Autowired
    IZzTeacherService teacherService;

    @Autowired
    IZzSchoolService zzSchoolService;

    @Override
    public Result<List<ApiZzPictureBookNodeVO>> queryAllNode(QueryAllZzPictureNode data) {
        LambdaQueryWrapper<ZzPictureNode> lambdaQueryWrapper = Wrappers.lambdaQuery(ZzPictureNode.class);
        lambdaQueryWrapper.eq(ZzPictureNode::getPictureBookId, data.getId());
        lambdaQueryWrapper.eq(ZzPictureNode::getNodeType, data.getType());
        if (1 == data.getType()) {
            lambdaQueryWrapper.apply("id in(select node_id from zz_subject_content where deleted=0)");
        }
        lambdaQueryWrapper.orderByAsc(ZzPictureNode::getSortNo).orderByAsc(ZzPictureNode::getId);
        List<ZzPictureNode> zzPictureNodeList = zzPictureNodeService.list(lambdaQueryWrapper);
        Result<List<ApiZzPictureBookNodeVO>> result = new Result<>();
        result.setResultCode(ResultEnum.SUCCESS.getCode());
        result.setResultMessage(ResultEnum.SUCCESS.getDesc());
        String config = sysConfigService.selectConfigByKeyCache(ConfigEnums.TASK_PICTURE_NODE_ICON.getCode());
        JSONObject obj = new JSONObject();
        if (StringUtils.isNotBlank(config)) {
            obj = JSON.parseObject(config);
        }
        List<ApiZzPictureBookNodeVO> zzPictureBookNodeVOList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(zzPictureNodeList)) {
            JSONObject finalObj = obj;
            if (SecurityUtils.isStu()) {
                for (ZzPictureNode zzPictureNode : zzPictureNodeList) {
                    ApiZzPictureBookNodeVO apiZzPictureBookNodeVO = new ApiZzPictureBookNodeVO();
                    apiZzPictureBookNodeVO.setId(zzPictureNode.getId());
                    apiZzPictureBookNodeVO.setNodeName(zzPictureNode.getNodeName());
                    apiZzPictureBookNodeVO.setIconNURL(MapUtils.getString(finalObj, apiZzPictureBookNodeVO.getNodeName() + "_n", ""));
                    apiZzPictureBookNodeVO.setIconSURL(MapUtils.getString(finalObj, apiZzPictureBookNodeVO.getNodeName() + "_s", ""));
                    apiZzPictureBookNodeVO.setFinishFlag(CommonEnums.NO);
                    //做题数量
                    long answerCount = zzExerciseBookService.count(Wrappers.lambdaQuery(ZzExerciseBook.class)
                                    .eq(ZzExerciseBook::getStudentId,SecurityUtils.getUserId())
                            .exists("select id from zz_subject_content b where b.deleted=0" +
                                    " and EXISTS (" +
                                    " select 1 from zz_picture_node c where c.deleted=0" +
                                    " and c.id=b.node_id and c.node_type=2 and EXISTS(select 1 from zz_picture_node d where d.deleted=0 " +
                                    " and d.id={0} and c.p_node_id=d.id" +
                                    " )" +
                                    " ) and b.id=zz_exercise_book.content_id", zzPictureNode.getId())

                    );
                    if(answerCount>0){
                        //题目数量
                        long count = this.zzSubjectContentService.count(
                                Wrappers.lambdaQuery(ZzSubjectContent.class)
                                        .exists("select 1 from zz_picture_node a where a.id=zz_subject_content.node_id and a.node_type=2 and a.deleted=0 and a.p_node_id={0}", zzPictureNode.getId())
                        );
                        if (count - answerCount <= 0) {
                            apiZzPictureBookNodeVO.setFinishFlag(CommonEnums.YES);
                    }
                    }
                    zzPictureBookNodeVOList.add(apiZzPictureBookNodeVO);
                }
            } else {
                for (ZzPictureNode zzPictureNode : zzPictureNodeList) {
                    ApiZzPictureBookNodeVO apiZzPictureBookNodeVO = new ApiZzPictureBookNodeVO();
                    apiZzPictureBookNodeVO.setId(zzPictureNode.getId());
                    apiZzPictureBookNodeVO.setNodeName(zzPictureNode.getNodeName());
                    apiZzPictureBookNodeVO.setIconNURL(MapUtils.getString(finalObj, apiZzPictureBookNodeVO.getNodeName() + "_n", ""));
                    apiZzPictureBookNodeVO.setIconSURL(MapUtils.getString(finalObj, apiZzPictureBookNodeVO.getNodeName() + "_s", ""));
                    apiZzPictureBookNodeVO.setFinishFlag(CommonEnums.YES);
                    zzPictureBookNodeVOList.add(apiZzPictureBookNodeVO);
                }
            }
        }
        result.setData(zzPictureBookNodeVOList);
        return result;
    }

    @Override
    public Result<List<ApiZzPictureContentVO>> queryPictureByNodeContent(QueryPictureByNodeContent data) {
        LambdaQueryWrapper<ZzSubjectContent> lambdaQueryWrapper = Wrappers.lambdaQuery(ZzSubjectContent.class);
        lambdaQueryWrapper.select(ZzSubjectContent::getId);
        lambdaQueryWrapper.eq(ZzSubjectContent::getState, CommonEnums.YES.getCode());
        lambdaQueryWrapper.apply("node_id in(select id from zz_picture_node where  deleted={0} and id={1})", DeletedEnums.NO.getCode(), data.getNodeId());
        lambdaQueryWrapper.orderByAsc(ZzSubjectContent::getSortNo);
        List<ZzSubjectContent> zzSubjectContentList = zzSubjectContentService.list(lambdaQueryWrapper);
        Result<List<ApiZzPictureContentVO>> result = new Result<>();
        result.setResultCode(ResultEnum.SUCCESS.getCode());
        result.setResultMessage(ResultEnum.SUCCESS.getDesc());
        result.setData(Optional.ofNullable(zzSubjectContentList).orElse(Lists.newArrayList()).stream().map(zzSubjectContent -> {
            ApiZzPictureContentVO apiZzPictureContentVO = new ApiZzPictureContentVO();
            apiZzPictureContentVO.setId(zzSubjectContent.getId());
            apiZzPictureContentVO.setStudyFlag(studyFlag(zzSubjectContent.getId()));
            return apiZzPictureContentVO;
        }).collect(Collectors.toList()));
        return result;
    }


    @Override
    public Result<List<ApiZzPictureBookNodeVO>> queryDaysNode(QueryPictureByNodeContent data) {
        LambdaQueryWrapper<ZzPictureNode> lambdaQueryWrapper = Wrappers.lambdaQuery(ZzPictureNode.class);
        lambdaQueryWrapper.eq(ZzPictureNode::getPictureBookId, data.getId());
        lambdaQueryWrapper.eq(ZzPictureNode::getpNodeId, data.getNodeId());
        lambdaQueryWrapper.apply("id in(select node_id from zz_subject_content where deleted=0)");
        lambdaQueryWrapper.orderByAsc(ZzPictureNode::getSortNo).orderByAsc(ZzPictureNode::getId);

        List<ZzPictureNode> zzPictureNodeList = zzPictureNodeService.list(lambdaQueryWrapper);

        String config = sysConfigService.selectConfigByKeyCache(ConfigEnums.TASK_PICTURE_NODE_ICON.getCode());
        JSONObject obj = new JSONObject();
        if (StringUtils.isNotBlank(config)) {
            obj = JSON.parseObject(config);
        }
        JSONObject finalObj = obj;
        Result<List<ApiZzPictureBookNodeVO>> result = new Result<>();
        result.setResultCode(ResultEnum.SUCCESS.getCode());
        result.setResultMessage(ResultEnum.SUCCESS.getDesc());
        result.setData(Optional.ofNullable(zzPictureNodeList).orElse(Lists.newArrayList()).stream().map(zzSubjectContent -> {
            ApiZzPictureBookNodeVO apiZzPictureBookNodeVO = new ApiZzPictureBookNodeVO();
            apiZzPictureBookNodeVO.setId(zzSubjectContent.getId());
            apiZzPictureBookNodeVO.setNodeName(zzSubjectContent.getNodeName());
            apiZzPictureBookNodeVO.setIconNURL(MapUtils.getString(finalObj, apiZzPictureBookNodeVO.getNodeName() + "_n", ""));
            apiZzPictureBookNodeVO.setIconSURL(MapUtils.getString(finalObj, apiZzPictureBookNodeVO.getNodeName() + "_s", ""));
            return apiZzPictureBookNodeVO;
        }).collect(Collectors.toList()));
        return result;
    }

    @Override
    public Result<PageData<ApiZzPictureBookVO>> queryPageNews(QueryPageZzPictureBook data) {
        Result<PageData<ApiZzPictureBookVO>> result = new Result<>();
        LoginUser loginUser = SecurityUtils.getLoginUser();
        IPage<ZzPictureBook> page = new Page<>();
        if (SecurityUtils.isTeacher()) {
            //学校的所有绘本
            ZzTeacher zzTeacher = this.teacherService.getById(SecurityUtils.getUserId());
            if (null != zzTeacher) {
                List<Integer> stateList = Lists.newArrayList();
                stateList.add(CommonEnums.YES.getCode());
                stateList.add(CommonEnums.NO.getCode());
                //# 老师 查询他所在学校 解锁的所有绘本列表
                if (null != zzTeacher) {
                    if (zzSchoolService.isTestSchoolFlag(zzTeacher.getSchoolId())) {
                        page = zzPictureBookService.page(Page.of(data.getPageNum(), data.getPageSize()),
                                Wrappers.lambdaQuery(ZzPictureBook.class)
                                        .eq(StringUtils.isNotBlank(data.getLevel()), ZzPictureBook::getLevel, data.getLevel())
                                        .eq(null != data.getUnitId(), ZzPictureBook::getUnitId, data.getUnitId())
                                        .orderByAsc(ZzPictureBook::getSortNo, ZzPictureBook::getId)
                        );
                    } else {
                        page = zzPictureBookService.apiMiniProZzPictureBookQueryPageNews(Page.of(data.getPageNum(), data.getPageSize()), data.getLevel(), zzTeacher.getSchoolId(), data.getUnitId(), stateList);
                    }
                }


            }
        } else {
            ZzStudent zzStudent = this.zzStudentService.getById(loginUser.getUserId());
            page = this.zzPictureBookService.apiQueryZzPictureBookPageNews(Page.of(data.getPageNum(), data.getPageSize()), loginUser.getUserId(), zzStudent.getSchoolId(), data.getUnitId());

        }
        List<ZzPictureBook> list = page.getRecords();
        List<Long> fileIdList = Optional.ofNullable(list).orElse(Lists.newArrayList()).stream().flatMap(zzPictureBook -> {
            List<Long> coverList = Optional.ofNullable(zzPictureBook.getCover()).map(json -> JSON.parseArray(json, Long.class)).orElse(Lists.newArrayList());
            List<Long> videoList = Optional.ofNullable(zzPictureBook.getVideo()).map(json -> JSON.parseArray(json, Long.class)).orElse(Lists.newArrayList());
            return Stream.concat(coverList.stream(), videoList.stream());
        }).collect(Collectors.toList());
        Map<Long, ZzUploadFileVO> fileMap = zzUploadFileManager.getMapByIdList(fileIdList);
        PageData<ApiZzPictureBookVO> pageData = new PageData<>(page.getTotal(), Optional.ofNullable(page.getRecords()).orElse(Lists.newArrayList()).stream().map(zzPictureBook -> {
            ApiZzPictureBookVO apiZzPictureBookVO = new ApiZzPictureBookVO();
            BeanUtils.copyProperties(zzPictureBook, apiZzPictureBookVO);
            apiZzPictureBookVO.setUnLockDate(0L);
            if (null != zzPictureBook.getUnLockDate()) {
                apiZzPictureBookVO.setUnLockDate(zzPictureBook.getUnLockDate().atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli());
            }
            List<Long> coverList = Optional.ofNullable(zzPictureBook.getCover()).map(json -> JSON.parseArray(json, Long.class)).orElse(Lists.newArrayList());
            apiZzPictureBookVO.setCoverZzUploadFileVO(coverList.stream().map(id -> {
                ZzUploadFileVO zzUploadFileVO = fileMap.get(id);
                return zzUploadFileVO;
            }).filter(Objects::nonNull).collect(Collectors.toList()));

            List<Long> videoList = Optional.ofNullable(zzPictureBook.getVideo()).map(json -> JSON.parseArray(json, Long.class)).orElse(Lists.newArrayList());
            apiZzPictureBookVO.setVideoZzUploadFileVO(videoList.stream().map(id -> {
                ZzUploadFileVO zzUploadFileVO = fileMap.get(id);
                return zzUploadFileVO;
            }).filter(Objects::nonNull).collect(Collectors.toList()));
            ZzCourse zzCourse = zzCourseService.getById(zzPictureBook.getUnitId());
            if (null != zzCourse) {
                apiZzPictureBookVO.setUnitName(zzCourse.getName());
            }
            apiZzPictureBookVO.setLockFlag(CommonEnums.YES);
            return apiZzPictureBookVO;
        }).collect(Collectors.toList()));
        result.setData(pageData);
        result.setResultCode(ResultEnum.SUCCESS.getCode());
        result.setResultMessage(ResultEnum.SUCCESS.getDesc());
        return result;
    }

    @Override
    public Result<List<ZzCourse>> courseListNews(QueryUnitList data) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Result<List<ZzCourse>> result = new Result<>();
        List<ZzCourse> list = Lists.newArrayList();
        if (SecurityUtils.isTeacher()) {
            //# 老师 查询他所在学校 解锁的所有绘本列表
            ZzTeacher zzTeacher = this.teacherService.getById(SecurityUtils.getUserId());
            if (null != zzTeacher) {
                if (zzSchoolService.isTestSchoolFlag(zzTeacher.getSchoolId())) {
                    list = zzCourseService.list(Wrappers.lambdaQuery(ZzCourse.class)
                            .orderByAsc(ZzCourse::getLevel, ZzCourse::getSortNo, ZzCourse::getId)
                    );
                } else {
                    list = zzCourseService.list(Wrappers.lambdaQuery(ZzCourse.class)
                            .eq(ZzCourse::getState, CommonEnums.YES.getCode())
                            .exists("select unit_id from zz_school_course where deleted=0 and school_id in(select id from zz_school where deleted=0 and id={0}) and unit_id=zz_course.id", zzTeacher.getSchoolId())
                            .orderByAsc(ZzCourse::getLevel, ZzCourse::getSortNo, ZzCourse::getId)
                    );
                }
            }
        } else if (SecurityUtils.isStu()) {
            ZzStudent zzStudent = this.zzStudentService.getById(loginUser.getUserId());
            Assert.notNull(zzStudent, "学生信息不存在");
            //不限制绘本状态-取消上线下线
            List<Integer> stateList = Lists.newArrayList();
            stateList.add(CommonEnums.YES.getCode());
            stateList.add(CommonEnums.NO.getCode());
            list = zzCourseService.getStuCourseListNews(loginUser.getUserId(), zzStudent.getSchoolId(), data.getLevel(), stateList);
        }
        result.setData(list);
        result.setResultCode(ResultEnum.SUCCESS.getCode());
        result.setResultMessage(ResultEnum.SUCCESS.getDesc());
        return result;
    }

    private CommonEnums studyFlag(Long id) {
        String redisKey = zzExerciseBookManager.buildCacheKey();
        String filedKey = zzExerciseBookManager.buildFiledKey(id);
        HashOperations hashOperations = redisTemplate.opsForHash();
        boolean exists = hashOperations.hasKey(redisKey, filedKey);
        ZzExerciseBook zzExerciseBook = null;
        if (exists) {
            return CommonEnums.YES;
        } else {
            if (null != zzExerciseBookService.getByStudentIdAndSubjectId(SecurityUtils.getUserId(), id)) {
                return CommonEnums.YES;
            }
        }
        return CommonEnums.NO;
    }

}
